/****************************************************
	文件：ClassObjectPool.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/7/12 16:27:7
	功能：类对象池
*****************************************************/

using System.Collections.Generic;

namespace HTSpider
{
    public class ClassObjectPool<T> where T : class, new()
    {
        /// <summary>
        /// 最大容量，构造时确定，0 为无限容量
        /// </summary>
        private int mMaxCount;
        /// <summary>
        /// 从对象池中分配出去，还未回收的对象数量
        /// </summary>
        private int mNoRecycleCount;
        /// <summary>
        /// 对象池缓存
        /// </summary>
        private Stack<T> mPool;

        public ClassObjectPool(int maxCount)
        {
            mMaxCount = maxCount;
            mPool = new Stack<T>();
            for (int i = 0; i < mMaxCount; i++)
            {
                mPool.Push(new T());
            }
        }

        /// <summary>
        /// 分配对象池中的对象
        /// </summary>
        /// <param name="createAlthoughtPoolIsEmpty">对象池为空时是否创建对象</param>
        /// <returns></returns>
        public T Spawn(bool createAlthoughtPoolIsEmpty)
        {
            T ret = null;
            if (mPool.Count > 0)
            {
                ret = mPool.Pop();
                if (ret == null)
                {
                    if (createAlthoughtPoolIsEmpty)
                    {
                        ret = new T();
                    }
                }
                mNoRecycleCount++;
            }
            else
            {
                if (createAlthoughtPoolIsEmpty)
                {
                    ret = new T();
                    mNoRecycleCount++;
                }
            }
            return ret;
        }
        /// <summary>
        /// 回收对象到对象池中（只有对象真的回收到对象池中 才返回true）
        /// </summary>
        /// <param name="obj">待回收的对象</param>
        /// <returns></returns>
        public bool Recycle(T obj)
        {
            if (obj == null) return false;
            if (mMaxCount > 0 && mPool.Count >= mMaxCount)
            {
                obj = null;
                mNoRecycleCount--;
                return false;
            }
            mPool.Push(obj);
            mNoRecycleCount--;
            return true;
        }
    }
}
